﻿using System;
using System.Collections.Generic;
using System.Drawing.Design;
using System.Linq;
using System.Windows.Forms.Design;
using DslModeling = global::Microsoft.VisualStudio.Modeling;
using devtm.AutoMapper.CustomCode.TemplateAdd;
using devtm.Editor.TypeSelector;
using Mono.Cecil;
using System.Diagnostics;
using CodeDomHelper.Types;


namespace devtm.AutoMapper
{

    public class ListeTypeTypeEditor : UITypeEditor
    {

        protected DslModeling.Store Store;
        
        


        /// <summary>
        /// Edits the specified object's value using the editor style indicated by the <see cref="M:System.Drawing.Design.UITypeEditor.GetEditStyle"/> method.
        /// </summary>
        /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that can be used to gain additional context information.</param>
        /// <param name="provider">An <see cref="T:System.IServiceProvider"/> that this editor can use to obtain services.</param>
        /// <param name="value">The object to edit.</param>
        /// <returns>
        /// The new value of the object. If the value of the object has not changed, this should return the same object it was passed.
        /// </returns>
        public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
        {

            IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            if (edSvc != null)
            {


                var TargetAs = context.PropertyDescriptor.Name == "TargetAs";
                string TargetType = string.Empty;
                
                TypeElementShape g;
                if (context.Instance.GetType().IsArray)
                    g = ((Object[])context.Instance)[0] as TypeElementShape;
                else
                    g = context.Instance as TypeElementShape;


                if (g != null)
                {
                    TypeElement Instance = g.Subject as TypeElement;

                    if (Instance != null)
                        this.Store = Instance.Store;

                }
                else
                {
                    ItemMap g1;
                    if (context.Instance.GetType().IsArray)
                        g1 = ((Object[])context.Instance)[0] as ItemMap;
                    else
                        g1 = context.Instance as ItemMap;

                    if (g1 != null)
                        this.Store = g1.Store;

                    var tt = string.IsNullOrEmpty(g1.TargetItemType)
                        ? BuildTypeExpression.Analyse(g1.TargetType)
                        : BuildTypeExpression.Analyse(g1.TargetType);

                    TargetType = tt.Namespace;
                    if (!string.IsNullOrEmpty(TargetType))
                        TargetType += ".";
                    TargetType += tt.Name;


                }

                if (this.Store != null)
                {

                    using (CustomTypeRepository repository = CustomTypeRepository.Instance(this.Store, false))
                    {

                        WindowsSelectType frm = null;

                        try
                        {
                            frm = new WindowsSelectType();
                        }
                        catch (System.Exception ex)
                        {
                            Helpers._output.WriteLine(ex.ToString());
                            return value;
                        }

                        Predicate<TypeDefinition> predicate = null;

                        if (TargetAs)
                            predicate = (type) => { return type != null & type.IsPublic && (type.InheritFrom(TargetType) || type.GetInterfaces().Select( t => t.FullName).Contains(TargetType)); };
                        else
                            predicate = (type) => { return type != null & type.IsPublic; };

                        


                        try
                        {

                            frm.SetList(repository, predicate, value as string, true);

                            if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                            {
                                TypeDefinition t1 = frm.SelectedItem as TypeDefinition;
                                value = t1.AssemblyQualifiedName;
                            }

                        }
                        catch (System.Exception ex)
                        {
                            Helpers._output.WriteLine(ex.ToString());
                            return value;

                        }


                    }

                }

            }

            return value;

        }

        



        public override bool IsDropDownResizable
        {
            get
            {
                return false;
            }
        }

        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {

            TypeElementShape g;
            if (context.Instance.GetType().IsArray)
                g = ((Object[])context.Instance)[0] as TypeElementShape;
            else
                g = context.Instance as TypeElementShape;

            if (g != null)
            {
                TypeElement Instance = g.Subject as TypeElement;

                if (Instance != null)
                    return UITypeEditorEditStyle.Modal;

            }
            else
            {
                ItemMap g1;
                if (context.Instance.GetType().IsArray)
                    g1 = ((Object[])context.Instance)[0] as ItemMap;
                else
                    g1 = context.Instance as ItemMap;

                if (g1 != null)                
                    return UITypeEditorEditStyle.Modal; 
                
            }

            return UITypeEditorEditStyle.None;
            //return base.GetEditStyle(context);
        }

    }
}
